/*
 * client.c
 *
 *  Created on: Apr 29, 2012
 *      Author: root
 */

#include	<string.h>
#include	<stdlib.h>
#include	"files.h"

#define MAXLINE	4096
#define	MAXID	128


static Client *clientList = NULL;
static Client *freeList = NULL;

Client *
getClientList() {
	return (clientList);
}

char *
getUser(Client *client)
{
	if ( client->user[0] == '\0')
		return (NULL);
	return(client->user);
}

int
getSocket(Client *client)
{
	if (client == NULL)
		return (-1);
	else
		return (client->connfd);
}

Client *
findClient(char *user) {
	Client *client;

	for (client = clientList; client != NULL; client = client->next)
		if (!strcmp(client->user, user))
			return (client);
	return (NULL);
}

/* Create a client and insert it to clientList
 * Returns: pointer to client node
 *          NULL if couldn't create (Connection should be closed and rejected)
 */
Client *
createClient(int connfd){
	Client *c;

	if (freeList == NULL) {
		// If freeList is empty, allocate memory for a client.
		if ( 	((c = (Client *) malloc (sizeof(Client))) != NULL) &&
				((c->user = (char *) malloc((size_t) MAXID)) != NULL) &&
				((c->from = (char *) malloc((size_t) MAXLINE)) !=NULL) &&
				((c->readBuffer = (ReadBuffer *) createRbuf(MAXLINE)) !=NULL)
				) {
			c->next = freeList;
			freeList = c;
		} else
			return (NULL);	// Not enough memory. return NULL
	}

	// Get a client node from freeList
	c = freeList;
	freeList = freeList->next;

	// Initialize the client node
	c->connfd = connfd;
	*(c->user) = '\0';
	c->state = 0;
	initRbuf(c->readBuffer);

	// Insert the client node in front of clientList
	c->next = clientList;
	clientList = c;

	return (c);	// returns pointer to the client node
}

/* Destroy the client
 * 		Note: allocated memory will be reused.
 */
void
destroyClient(Client *c) {
	Client *cur, **pre;

	// remove the client from clientList
	for  (pre = &clientList, cur = clientList; (cur != c) ; pre = &(cur->next), cur = cur->next); // find predecessor
	*pre = c->next;	//remove the client

	// insert it to the front of freeList
	c->next = freeList;
	freeList = c;
}

ssize_t
readClient(Client *client)
{
	return (readBuf(client->readBuffer, client->connfd));
}

